COM Part 2

We already covered a lot of ground in COM part 1, and by now you should have practised enough with COM objects to get a feel for them. The stuff below you either need to know Jscript or VBscript, though you can use perlscript, and a whole host of other languages - however support is not very widespread for these extensions to WSH.

An Indepth Look At What We Covered

Last tutorial, we used the spell checker to get a true or false value back from excel.application. To do it we used $com(), so it is there we will look in a much more indepth manner.

$com(name,member,method,type1,value1,...,typeN,valueN)

Name - like a socket name, the name you used when you did a /comopen NAME excel.application. If you get this bit wrong, obviously mIRC won't work with it right, as it doesn't know which thing its working with.

Member - The function/method/sub you are going to call with your code. You can find out which methods are available via the Object Browser in VB for Applications. See the first tutorial for more information on this.

Method - One of the things that Encapsulation entails is the hiding of code. Accordingly, its a no no to directly set a value - you should call the get/set function associated with that value. In other words, you wouldn't go to every yellow pages and change your phone number manually with a blue pen, you'd ring the company to change your phone number through them and rely on them to do all of the leg work.

The good thing about this is a "set method" can validate data - you don't want to put "FISH" in a date of birth field as that may mangle your code. Also, it can aide nifty stuff like undo features, which we take more or less for granted.

Every language implements these ideas slightly differently, but since its COM then its easy. In the example before we used we put "3" as the method.

method - Combination of the following values added together:
1 = DISPATCH_METHOD
2 = DISPATCH_PROPERTYGET
4 = DISPATCH_PROPERTYPUT
8 = DISPATCH_PROPERTYPUTREF
1 + 2 = 3, so we called BOTH DISPATCH_METHOD (treat the get method AS a get method rather than a property) and DISPATCH_PROPERTYGET, which also specified it was a property.

  if ($com(excel,checkspelling,1,string,test) == 0) { 
    echo $com failed 
    goto finish 
  }
  echo Spelled ok?: $com(excel).result 
Here we simply called "DISPATCH_METHOD", as Excel.Application.CheckSpelling is not a property.

If you don't get your code to work, try different values at random - its how I learnt. I haven't really found a use for DISPATCH_PROPERTYPUTREF, but I assume its got some purpose.

Type - This bit is a little trickier. First of all, I think I might need to digress a little. In C/C++, Java, etc you need to specify a RETURN TYPE of a method. This might be as follows:

Java:
public static void main(String args[]) {
  /*..Code..*/
}

C/C++
int main() {
  /*..Code..*/
  return 0;
}
As you can see above, both examples have different return types. VOID indicates that nothing will be returned. Int specifies a whole number will be returned. C/C++ programs often use integers for error control, for instance a non zero value means that somewhere an error has occured. Java does things differently, but that doesn't concern us.

The reason languages such as C or C++ or even Java specify return types is for memory allocation purposes. To store a whole number between 0 and 255 takes less memory than storing a string of characters, one after the other (Which is more or less what "strings" are, character arrays).

Visual Basic 6 is a monster. It does not force users to specify a return type, and in general isn't very fussy about stuff becasue it uses its primitive type Variant. This is a big reason why Visual Basic 6 is slow; its poor use of memory.

If your not getting it I suppose I should cut to the chase. Here's a list of types, their vb equivilants.

VB	Other	Description
currency
long	
single	
string		An array of characters in the form of a "string". 
	i1	Whole number range 0-255
	i2
double		Decimal number with up to ten digits of precision
byte		
	i4
	ui1
	ui2
	ui4
integer	int	Integer - a whole number from 0 to 65,535
	uint	Unsigned Integer - see below
	r4
	r8
	cy
date	date	A date
	decimal	A decimal number
boolean	bool	Boolean, True or False (may be represented as 0 and non 0 values)
	bstr	Binary String
variant	variant	Mixed type, could be part string, part int, etc.
	dispatch
	unknown
	error
Whats all this signed/unsigned nonsense? There are five 'atomic' (base) data types in C - char, int, float, double, void - but sometimes thats just not enough. The difference between signed and unsigned is best shown by example.
Signed:
01111111 11111111 = 32,767

if the high order bit (the zero at the start) were set to 1
this would be considered -1
Signed:
11111111 11111111 = -1
Unsigned:
11111111 11111111 = 65,535
As you can see the difference between signed and unsigned are several orders of magnitude. You can also pass varible by reference, but this will not concern you very often, in the same manner than signed and unsigned data types will not concern you often.

To sum up this bit, the most common types you will use are:

  • String
  • Bool
  • Int

    value - The data of type TYPE to pass to the method/property.

    You'll either get a 0, failed, or a 1, didn't fail from each call to $com.



    Making IE obey my beck and call

    Internet Explorer provides a COM interface, called, strangely enough, InternetExplorer.Application. For our next challenge, we are going to write a page dynamically via COM. To do it you will need to use InternetExplorer.Application.Document.Body.InnerHTML = "insert html here.".

    I will tell you now, however, that you are going to run into trouble. You cannot create a new object "InternetExplorer.Application.Document.Body.InnerHTML". I'm sure there actually is a way to do it (poss with putref), but its time for us to take the shortest route to the goal. Online started posting snippets of COM automation using the below technique, so in regards to mIRC as far as I'm concerned he pioneered this workaround. But, let it be known, that ever since WSH came out, virii writers have been making use/abuse of this style of workaround.

    The workaround is this - WSH. The code below shows us how to correctly access properties, methods etc of sub objects, like the 'document.body.innerhtml' property.

    ieTest {
      ;Below code is written in VBScript
    
      window -h @@ 
      var %a = aline @@
    
      %a Set objIE = CreateObject("InternetExplorer.Application")
      ;If this is not done, you will get errors, as there would be no 'documents'
      ;set up in objIE
      %a objIE.Navigate("about:blank")
      %a objIE.Document.Body.InnerHTML = "test"
      %a objIE.Visible = 1
    
      savebuf @@ temp.vbs
    
      window -c @@
    
      ; run it and wait until finished
    
      .comopen run WScript.Shell
      .comclose run $com(run,Run,3,bstr,wscript temp.vbs,uint,5,bool,true)
    
      .remove temp.vbs
      return %n
    }
    
    For more info on IE COM Automation, try here or Google.

    What's next?

    Well here's where I recommend you read some more stuff. Find stuff on VBscript, Jscript, Encapsulation, C/C++ Primitive Data Types, Visual Basic Data Types, COM Automation with IE, Word, Excel, Office, Windows Scripting Host, Outlook, & MSN Messanger.